From 1875b36bd16aaefd7db0b855061b8529a1eb544b Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bartosz=20Dziewo=C5=84ski?= Date: Sat, 31 May 2014 22:55:40 +0200 Subject: [PATCH] Vector: Fix conflicts of "Actions" dropdown with collapsibleTabs Follow-up to I09c8031c. * Don't override the width of the "Actions" dropdown when collapsing tabs. The width was hardcoded to 24px, using the actual width now. This only matters when the "Actions" dropdown disappears completely (it has no items inside), and then something gets moved inside it causing it to reappear. * Use the same collapsing speed for the dropdown and the tabs. * Account for the width of the "Actions" dropdown if the expansion would hide it. This issue was there before, but was not that noticeable because the width of the dropdown was negligible. (This required making the calculateTabDistance() function in collapsibleTabs part of the public API.) * Do not collapse if the width of the dropdown would exceed the width of the tab we're collapsing. This issue was there before as well, but in practice the dropdown was always smaller; this is not necessarily the case now, for example in Lithuanian (lt). Bug: 44591 Change-Id: Id4548ea388fd9f4341dd78bb132c716feb14b137 --- skins/vector/collapsibleTabs.js | 63 ++++++++++++++++----------------- skins/vector/vector.js | 49 ++++++++++++++++++++++--- 2 files changed, 75 insertions(+), 37 deletions(-) diff --git a/skins/vector/collapsibleTabs.js b/skins/vector/collapsibleTabs.js index 93444339e5..e24bea95d9 100644 --- a/skins/vector/collapsibleTabs.js +++ b/skins/vector/collapsibleTabs.js @@ -36,34 +36,6 @@ $.collapsibleTabs.handleResize(); return this; }; - /** - * Returns the amount of horizontal distance between the two tabs groups - * (#left-navigation and #right-navigation), in pixels. If negative, this - * means that the tabs overlap, and the value is the width of overlapping - * parts. - * - * Used in default expandCondition and collapseCondition. - * - * @return {Numeric} distance/overlap in pixels - */ - function calculateTabDistance() { - var $leftTab, $rightTab, leftEnd, rightStart; - - // In RTL, #right-navigation is actually on the left and vice versa. - // Hooray for descriptive naming. - if ( !rtl ) { - $leftTab = $( '#left-navigation' ); - $rightTab = $( '#right-navigation' ); - } else { - $leftTab = $( '#right-navigation' ); - $rightTab = $( '#left-navigation' ); - } - - leftEnd = $leftTab.offset().left + $leftTab.width(); - rightStart = $rightTab.offset().left; - - return rightStart - leftEnd; - } $.collapsibleTabs = { instances: [], boundEvent: null, @@ -74,13 +46,12 @@ shifting: false, expandCondition: function ( eleWidth ) { // If there are at least eleWidth + 1 pixels of free space, expand. - // We add 1 because .width() will truncate fractional values - // but .offset() will not. - return calculateTabDistance() >= (eleWidth + 1); + // We add 1 because .width() will truncate fractional values but .offset() will not. + return $.collapsibleTabs.calculateTabDistance() >= eleWidth + 1; }, collapseCondition: function () { // If there's an overlap, collapse. - return calculateTabDistance() < 0; + return $.collapsibleTabs.calculateTabDistance() < 0; } }, addData: function ( $collapsible ) { @@ -202,6 +173,34 @@ } } ) ); + }, + /** + * Returns the amount of horizontal distance between the two tabs groups + * (#left-navigation and #right-navigation), in pixels. If negative, this + * means that the tabs overlap, and the value is the width of overlapping + * parts. + * + * Used in default expandCondition and collapseCondition. + * + * @return {Numeric} distance/overlap in pixels + */ + calculateTabDistance: function () { + var $leftTab, $rightTab, leftEnd, rightStart; + + // In RTL, #right-navigation is actually on the left and vice versa. + // Hooray for descriptive naming. + if ( !rtl ) { + $leftTab = $( '#left-navigation' ); + $rightTab = $( '#right-navigation' ); + } else { + $leftTab = $( '#right-navigation' ); + $rightTab = $( '#left-navigation' ); + } + + leftEnd = $leftTab.offset().left + $leftTab.width(); + rightStart = $rightTab.offset().left; + + return rightStart - leftEnd; } }; diff --git a/skins/vector/vector.js b/skins/vector/vector.js index 58ba2af2c6..c6036158fb 100644 --- a/skins/vector/vector.js +++ b/skins/vector/vector.js @@ -35,28 +35,67 @@ jQuery( function ( $ ) { /** * Collapsible tabs for Vector */ - var $cactions = $( '#p-cactions' ); + var $cactions = $( '#p-cactions' ), + $tabContainer = $( '#p-views ul' ), + originalDropdownWidth = $cactions.width(); // Bind callback functions to animate our drop down menu in and out // and then call the collapsibleTabs function on the menu - $( '#p-views ul' ) + $tabContainer .bind( 'beforeTabCollapse', function () { // If the dropdown was hidden, show it if ( $cactions.hasClass( 'emptyPortlet' ) ) { $cactions .removeClass( 'emptyPortlet' ) .find( 'h3' ) - .css( 'width', '1px' ).animate( { 'width': '24px' }, 390 ); + .css( 'width', '1px' ).animate( { 'width': originalDropdownWidth }, 'normal' ); } } ) .bind( 'beforeTabExpand', function () { // If we're removing the last child node right now, hide the dropdown if ( $cactions.find( 'li' ).length === 1 ) { - $cactions.find( 'h3' ).animate( { 'width': '1px' }, 390, function () { + $cactions.find( 'h3' ).animate( { 'width': '1px' }, 'normal', function () { $( this ).attr( 'style', '' ) .parent().addClass( 'emptyPortlet' ); }); } } ) - .collapsibleTabs(); + .collapsibleTabs( { + expandCondition: function ( eleWidth ) { + // (This looks a bit awkward because we're doing expensive queries as late as possible.) + + var distance = $.collapsibleTabs.calculateTabDistance(); + // If there are at least eleWidth + 1 pixels of free space, expand. + // We add 1 because .width() will truncate fractional values but .offset() will not. + if ( distance >= eleWidth + 1 ) { + return true; + } else { + // Maybe we can still expand? Account for the width of the "Actions" dropdown if the + // expansion would hide it. + if ( $cactions.find( 'li' ).length === 1 ) { + return distance >= eleWidth + 1 - originalDropdownWidth; + } else { + return false; + } + } + }, + collapseCondition: function () { + // (This looks a bit awkward because we're doing expensive queries as late as possible.) + // TODO The dropdown itself should probably "fold" to just the down-arrow (hiding the text) + // if it can't fit on the line? + + // If there's an overlap, collapse. + if ( $.collapsibleTabs.calculateTabDistance() < 0 ) { + // But only if the width of the tab to collapse is smaller than the width of the dropdown + // we would have to insert. An example language where this happens is Lithuanian (lt). + if ( $cactions.hasClass( 'emptyPortlet' ) ) { + return $tabContainer.children( 'li.collapsible:last' ).width() > originalDropdownWidth; + } else { + return true; + } + } else { + return false; + } + } + } ); } ); -- 2.20.1